﻿using Engine;
using Esprima;
using GameEntitySystem;
using MFTrain;
using System;
using System.Linq;
using TemplatesDatabase;
using Game;
using Random = Engine.Random;

namespace MFTrain
{
    public class SubsystemMFTrainBlockBehavior : SubsystemBlockBehavior
    {
        public SubsystemAudio m_subsystemAudio;

        public SubsystemBodies m_subsystemBodies;

        public SubsystemGameInfo m_subsystemGameInfo;

        public Random m_random = new Random();

        public override int[] HandledBlocks => new int[1]
        {
            MFTrainBlock.Index
        };

        public override bool OnUse(Ray3 ray, ComponentMiner componentMiner)
        {
            _ = componentMiner.Inventory;

            TerrainRaycastResult? terrainRaycastResult = componentMiner.Raycast<TerrainRaycastResult>(ray, RaycastMode.Digging);
            if (terrainRaycastResult.HasValue && Terrain.ExtractContents(terrainRaycastResult.Value.Value) == MFRailBlock.Index)
            {
                if (componentMiner.ActiveBlockValue == Terrain.MakeBlockValue(MFTrainBlock.Index, 0, 0))
                {
                    Vector3 position = new Vector3(terrainRaycastResult.Value.CellFace.Point) + new Vector3(0.5f, 0f, 0.5f);
                    Entity entity = DatabaseManager.CreateEntity(Project, "MFTrain", true);

                    var rotation = componentMiner.ComponentCreature.ComponentCreatureModel.EyeRotation.ToForwardVector2();
                    entity.FindComponent<ComponentMFTrain>(true).SetDirection(MFRailBlock.IsDirectionX(MFRailBlock.GetRailType(Terrain.ExtractData(terrainRaycastResult.Value.Value)))
                        ? rotation.Z < 0 ? 0 : 2
                        : rotation.X < 0 ? 1 : 3);
                    entity.FindComponent<ComponentBody>(true).Position = position;
                    entity.FindComponent<ComponentSpawn>(true).SpawnDuration = 0f;
                    Project.AddEntity(entity);
                    var componentTrain = entity.FindComponent<ComponentMFTrain>(true);
                    componentMiner.RemoveActiveTool(1);
                    m_subsystemAudio.PlaySound("Audio/BlockPlaced", 1f, 0f, position, 3f, true);
                    return true;
                }
                else if (componentMiner.ActiveBlockValue == Terrain.MakeBlockValue(MFTrainBlock.Index, 0, 1))
                {
                    TerrainRaycastResult result = terrainRaycastResult.Value;
                    SubsystemTerrain terrain = Project.FindSubsystem<SubsystemTerrain>();
                    int value = terrain.Terrain.GetCellValueFast(result.CellFace.X, result.CellFace.Y, result.CellFace.Z);
                    int data = Terrain.ExtractData(value);
                    if (Terrain.ExtractContents(value) == MFRailBlock.Index)
                    {
                        if (!MFRailBlock.IsBreaker(data)) terrain.ChangeCell(result.CellFace.X, result.CellFace.Y, result.CellFace.Z, Terrain.MakeBlockValue(MFRailBlock.Index, 0, MFRailBlock.SetBreaker(data)));
                        else terrain.ChangeCell(result.CellFace.X, result.CellFace.Y, result.CellFace.Z, Terrain.MakeBlockValue(MFRailBlock.Index, 0, MFRailBlock.ClearBreaker(data)));
                        Project.FindSubsystem<SubsystemAudio>().PlaySound("Audio/BlockPlaced", 1f, 0f, new Vector3(result.CellFace.X, result.CellFace.Y, result.CellFace.Z), 3f, true);
                        return true;
                    }
                }
            }

            return false;
        }

        public override void Load(ValuesDictionary valuesDictionary)
        {
            base.Load(valuesDictionary);
            m_subsystemAudio = Project.FindSubsystem<SubsystemAudio>(throwOnError: true);
            m_subsystemBodies = Project.FindSubsystem<SubsystemBodies>(throwOnError: true);
            m_subsystemGameInfo = Project.FindSubsystem<SubsystemGameInfo>(throwOnError: true);
        }
    }
}
